home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / System / Talking Clock Pro™ 2.0b2 / Talking Clock Pro Source / Extension / Source / main.c next >
Encoding:
C/C++ Source or Header  |  1993-09-04  |  16.7 KB  |  773 lines  |  [TEXT/KAHL]

  1. /*
  2.  * main.c
  3.  */
  4.  
  5. #include <Types.h>
  6. #include <appleevents.h>
  7. #include <speech.h>
  8. #include <aeregistry.h>
  9. #include <aeobjects.h>
  10. #include <Memory.h>
  11. #ifdef applec
  12. #include <SysEqu.h>
  13. #endif
  14. #include <Resources.h>
  15. #include <ToolUtils.h>
  16. #include <Folders.h>
  17. #include <Errors.h>
  18. #include <Packages.h>
  19. #include <GestaltEqu.h>
  20. #include <Desk.h>
  21.  
  22. #include "x.h"
  23. #include "util.h"
  24. #include "str.h"
  25. #include "notify.h"
  26. #include "TalkConstants.h"
  27.  
  28. /* FBA? */
  29. #define appe
  30.  
  31.  
  32. /* This will be used as a breathing hole for the error reporting routine */
  33. Handle err_safeguard = NULL ;
  34.  
  35.  
  36. void InstallHandlers ( void ) ;
  37.  
  38. FSSpec prefFile ;
  39. Boolean quit = 0 ;
  40.  
  41. typedef struct pref {
  42.     short    turnoverPeriod ;
  43.     char        talkOptionKey ;
  44.     char        pad1 ;
  45.     char        talkControlKey ;
  46.     char        pad2 ;
  47.     char        talkCommandKey ;
  48.     char        pad3 ;
  49.     char        talkShiftKey ;
  50.     char        pad4 ;
  51.     char        talkCapsLockKey ;
  52.     char        pad5 ;
  53.     char        talkConstantly ;
  54.     char        pad6 ;
  55. } Pref ;
  56.  
  57. Pref gPrefStruct ;
  58.  
  59.  
  60. static void
  61. InitMac ( void ) {
  62.  
  63.     if ( ( * ( long * ) 0x908 ) - 6000L < ( long ) GetApplLimit ( ) ) {
  64.         SetApplLimit ( ( void * ) ( ( * ( long * ) 0x908 ) - 6000L ) ) ; /* CurStackBase */
  65.     }
  66.     MaxApplZone ( ) ;
  67.     MoreMasters ( ) ;
  68.  
  69. #ifndef appe
  70.     InitGraf ( & qd . thePort ) ;
  71.     InitFonts ( ) ;
  72.     InitWindows ( ) ;
  73.     InitMenus ( ) ;
  74.     TEInit ( ) ;
  75.     InitDialogs ( NULL ) ;
  76. #endif
  77. }
  78.  
  79.  
  80. static void
  81. CreatePrefsFile ( FSSpec * file ) {
  82.  
  83. volatile short refNum = 0 , refTemp ;
  84. long len ;
  85.  
  86.     TRY {
  87.         FailErr ( FSpCreate ( file , 'pref' , 'pref' , smRoman ) ) ;
  88.         FailErr ( FSpOpenDF ( file , fsWrPerm , ( short * ) & refNum ) ) ;
  89.         len = sizeof ( gPrefStruct ) ;
  90.         FailErr ( SetEOF ( refNum , len ) ) ;
  91.         FailErr ( FSWrite ( refNum , & len , ( Ptr ) & gPrefStruct ) ) ;
  92.         refTemp = refNum ;
  93.         refNum = 0 ;
  94.         FailErr ( FSClose ( refTemp ) ) ;
  95.     } CATCH {
  96.         if ( refNum ) {
  97.             FSClose ( refNum ) ;
  98.         }
  99.         FSpDelete ( file ) ;
  100.     } DONE ;
  101. }
  102.  
  103.  
  104. static void
  105. ReadPrefsFile ( FSSpec * file ) {
  106.  
  107. volatile short refNum = 0 , refTemp ;
  108. long len ;
  109.  
  110.     TRY {
  111.         FailErr ( FSpOpenDF ( file , fsRdPerm , ( short * ) & refNum ) ) ;
  112.         len = sizeof ( gPrefStruct ) ;
  113.         FailErr ( FSRead ( refNum , & len , ( Ptr ) & gPrefStruct ) ) ;
  114.         refTemp = refNum ;
  115.         refNum = 0 ;
  116.         FailErr ( FSClose ( refTemp ) ) ;
  117.     } CATCH {
  118.         if ( refNum ) {
  119.             FSClose ( refNum ) ;
  120.         }
  121.     } DONE ;
  122. }
  123.  
  124.  
  125. static void
  126. WritePrefsFile ( FSSpec * file ) {
  127.  
  128. volatile short refNum = 0 , refTemp ;
  129. long len ;
  130.  
  131.     TRY {
  132.         FailErr ( FSpOpenDF ( file , fsWrPerm , ( short * ) & refNum ) ) ;
  133.         len = sizeof ( gPrefStruct ) ;
  134.         FailErr ( SetEOF ( refNum , len ) ) ;
  135.         FailErr ( FSWrite ( refNum , & len , ( Ptr ) & gPrefStruct ) ) ;
  136.         refTemp = refNum ;
  137.         refNum = 0 ;
  138.         FailErr ( FSClose ( refTemp ) ) ;
  139.     } CATCH {
  140.         if ( refNum ) {
  141.             FSClose ( refNum ) ;
  142.         }
  143.     } DONE ;
  144. }
  145.  
  146.  
  147. static void
  148. InitApp ( ) {
  149.  
  150. short vRefNum ;
  151. long parID ;
  152. Str63 name ;
  153.  
  154. Handle h ;
  155.  
  156.     err_safeguard = NewHandle ( 1024 ) ;
  157.     FailNil ( err_safeguard ) ;
  158.  
  159.     h = GetResource ( 'Pref' , 128 ) ;
  160.     FailNil ( h ) ;
  161.     BlockMove ( * h , & gPrefStruct , sizeof ( gPrefStruct ) ) ;
  162.     ReleaseResource ( h ) ;
  163.  
  164.     GetIndString ( name , 128 , 1 ) ;
  165.     FailErr ( FindFolder ( kOnSystemDisk , kPreferencesFolderType , kCreateFolder ,
  166.         & vRefNum , & parID ) ) ;
  167.     if ( fnfErr == FSMakeFSSpec ( vRefNum , parID , name , & prefFile ) ) {
  168.         CreatePrefsFile ( & prefFile ) ;
  169.     }
  170.     ReadPrefsFile ( & prefFile ) ;
  171.  
  172.     InstallHandlers ( ) ;
  173. }
  174.  
  175.  
  176. static void
  177. QuitApp ( void ) {
  178.  
  179. static Str255 quitStr ;
  180. unsigned long tick = TickCount ( ) + 300L ;
  181.  
  182.     GetIndString ( quitStr , 128 , 11 ) ;
  183.     while ( SpeechBusy ( ) && TickCount ( ) < tick ) {
  184.         SystemTask ( ) ;
  185.     }
  186.     FailErr ( SysSpeakString ( quitStr ) ) ;
  187.     WritePrefsFile ( & prefFile ) ;
  188.     tick = TickCount ( ) + 300L ;
  189.     while ( SpeechBusy ( ) && TickCount ( ) < tick ) {
  190.         SystemTask ( ) ;
  191.     }
  192. }
  193.  
  194.  
  195. static void
  196. ReportError ( short errCode , Boolean toQuit ) {
  197.  
  198. static Str15 codeStr ;
  199. static Str15 lineStr ;
  200. static Str63 fileStr ;
  201. static Str255 s ;
  202. static Str63 medStr ;
  203.  
  204.     DisposeHandle ( err_safeguard ) ;
  205.     err_safeguard = NULL ;
  206.  
  207. #ifdef FAILINFO
  208.     NumToString ( __err_line , lineStr ) ;
  209.     CopyC2P ( __err_file , fileStr ) ;
  210. #else
  211.     lineStr [ 0 ] = 0 ;
  212.     fileStr [ 0 ] = 0 ;
  213. #endif
  214.  
  215.     NumToString ( errCode , codeStr ) ;
  216.  
  217.     GetIndString ( s , 128 , 6 ) ;
  218.     ConcatPStrings ( s , codeStr ) ;
  219.     GetIndString ( medStr , 128 , 7 ) ;
  220.     ConcatPStrings ( s , medStr ) ;
  221.     ConcatPStrings ( s , fileStr ) ;
  222.     GetIndString ( medStr , 128 , 8 ) ;
  223.     ConcatPStrings ( s , medStr ) ;
  224.     ConcatPStrings ( s , lineStr ) ;
  225.     GetIndString ( medStr , 128 , 9 ) ;
  226.     ConcatPStrings ( s , medStr ) ;
  227.  
  228.     NotifyStr ( s ) ;
  229.  
  230.     err_safeguard = NewHandle ( 1024 ) ;
  231. }
  232.  
  233.  
  234. static Boolean
  235. CheckVersions ( void ) {
  236.  
  237. /* These are the typical System-7 checks (we assume System 6 which means
  238.  * WaitNextEvent is always implemented etc.)
  239.  */
  240. Boolean fine = 1 ;
  241.  
  242.     fine = fine && CheckGestaltBit ( gestaltFindFolderAttr , gestaltFindFolderPresent ) ;
  243.     fine = fine && CheckGestaltBit ( gestaltAppleEventsAttr , gestaltAppleEventsPresent ) ;
  244.     fine = fine && CheckGestaltBit ( gestaltAliasMgrAttr , gestaltAliasMgrPresent ) ;
  245.     fine = fine && CheckGestaltBit ( gestaltOSAttr , gestaltLaunchControl ) ;
  246.     fine = fine && CheckGestaltBit ( gestaltOSAttr , gestaltRealTempMemory ) ;
  247.     fine = fine && CheckGestaltBit ( gestaltOSAttr , gestaltTempMemTracked ) ;
  248.     fine = fine && SpeechAvailable ( ) ;
  249.     return fine ;
  250. }
  251.  
  252.  
  253. static void
  254. FailVersions ( void ) {
  255.  
  256. static Str255 s ;
  257.  
  258.     GetIndString ( s , 128 , 10 ) ;
  259.     NotifyStr ( s ) ;
  260.     ExitToShell ( ) ;
  261. }
  262.  
  263.  
  264. typedef struct talkTime {
  265.     short    hour ;
  266.     short    minutePeriod ;
  267. } TalkTime ;
  268.  
  269.  
  270. static void
  271. MakeTalkTime ( TalkTime * new ) {
  272.  
  273. unsigned long now ;
  274. DateTimeRec dtr ;
  275.  
  276.     GetDateTime ( & now ) ;
  277.     Secs2Date ( now , & dtr ) ;
  278.     new -> hour = dtr . hour ;
  279.     new -> minutePeriod = dtr . minute / 5 ;
  280.     if ( ! dtr . minute ) {
  281.         new -> minutePeriod = 0 ;
  282.     } else if ( new -> minutePeriod > gPrefStruct . turnoverPeriod ) {
  283.         new -> hour += 1 ;
  284.     }
  285. }
  286.  
  287.  
  288. static Boolean
  289. TimeTask ( TalkTime * old , TalkTime * new ) {
  290.  
  291. Boolean ret = 0 ;
  292.  
  293.     MakeTalkTime ( new ) ;
  294.     if ( gPrefStruct . talkConstantly ) {
  295.         if ( new -> minutePeriod != old -> minutePeriod ) {
  296.             ret = 1 ;
  297.         }
  298.         if ( new -> hour != old -> hour ) {
  299.             ret = 1 ;
  300.         }
  301.     }
  302.     return ret ;
  303. }
  304.  
  305.  
  306. static Boolean
  307. KeyCheck ( void ) {
  308.     if ( gPrefStruct . talkOptionKey && KeyIsDown ( 0x3a ) ) {
  309.         return 1 ;
  310.     }
  311.     if ( gPrefStruct . talkControlKey && KeyIsDown ( 0x3b ) ) {
  312.         return 1 ;
  313.     }
  314.     if ( gPrefStruct . talkCommandKey && KeyIsDown ( 0x37 ) ) {
  315.         return 1 ;
  316.     }
  317.     if ( gPrefStruct . talkShiftKey && KeyIsDown ( 0x38 ) ) {
  318.         return 1 ;
  319.     }
  320.     if ( gPrefStruct . talkCapsLockKey && KeyIsDown ( 0x39 ) ) {
  321.         return 1 ;
  322.     }
  323.     return 0 ;
  324. }
  325.  
  326.  
  327. static void
  328. SpeakDate ( void ) {
  329.  
  330. static Str255 date ;
  331. unsigned long now ;
  332.  
  333.     GetDateTime ( & now ) ;
  334.     IUDateString ( now , longDate , date ) ;
  335.     while ( SpeechBusy ( ) ) {
  336.         SystemTask ( ) ;
  337.     }
  338.     FailErr ( SysSpeakString ( date ) ) ;
  339. }
  340.  
  341.  
  342. static void
  343. Talk ( TalkTime * time ) {
  344.  
  345. static Str255 s ;
  346. static Str63 middle ;
  347.  
  348.     if ( ! time -> minutePeriod ) {
  349.         GetIndString ( s , 129 , time -> hour + 1 ) ;
  350.         if ( ! SpeechBusy ( ) ) {
  351.             FailErr ( SysSpeakString ( s ) ) ;
  352.             if ( ! time -> hour ) {
  353.                 SpeakDate ( ) ;
  354.             }
  355.         }
  356.     } else {
  357.         GetIndString ( s , 128 , 2 ) ;
  358.         GetIndString ( middle , 131 , time -> minutePeriod ) ;
  359.         ConcatPStrings ( s , middle ) ;
  360.         GetIndString ( middle , 130 , ( time -> hour % 24 ) + 1 ) ;
  361.         ConcatPStrings ( s , middle ) ;
  362.         GetIndString ( middle , 128 , 3 ) ;
  363.         ConcatPStrings ( s , middle ) ;
  364.         FailErr ( SysSpeakString ( s ) ) ;
  365.     }
  366. }
  367.  
  368.  
  369. static void
  370. Idle ( void ) {
  371.  
  372. EventRecord er ;
  373. static TalkTime lastTalk = { 47 , 111 } , talk ;
  374. Boolean doTalk = 0 ;
  375.  
  376.     if ( WaitNextEvent ( -1 , & er , 120L , NULL ) ) {
  377.         if ( er . what == kHighLevelEvent ) {
  378.             FailErr ( AEProcessAppleEvent ( & er ) ) ;
  379.         }
  380.     }
  381.     doTalk = TimeTask ( & lastTalk , & talk ) ;
  382.     doTalk |= KeyCheck ( ) ;
  383.     if ( doTalk ) {
  384.         Talk ( & talk ) ;
  385.         lastTalk = talk ;
  386.     }
  387. }
  388.  
  389.  
  390. void
  391. main ( void ) {
  392.  
  393.     InitMac ( ) ;
  394.     if ( ! CheckVersions ( ) ) {
  395.         FailVersions ( ) ;
  396.     }
  397.     TRY {
  398.         InitApp ( ) ;
  399.     runAgain :
  400.         while ( ! quit ) {
  401.             TRY {
  402.                 Idle ( ) ;
  403.             } CATCH {
  404.                 ReportError ( __err , 0 ) ;
  405.                 NO_PROPAGATE ;
  406.             } DONE ;
  407.         }
  408.         QuitApp ( ) ;
  409.     } CATCH {
  410.         ReportError ( __err , 1 ) ;
  411.         NO_PROPAGATE ;
  412.     } DONE ;
  413. }
  414.  
  415.  
  416. static pascal OSErr
  417. OpenApplication ( AppleEvent * event , AppleEvent * reply , long refCon ) {
  418.     return noErr ;
  419. }
  420.  
  421.  
  422. static pascal OSErr
  423. QuitApplication ( AppleEvent * event , AppleEvent * reply , long refCon ) {
  424.     quit = 1 ;
  425.     return noErr ;
  426. }
  427.  
  428.  
  429. static OSErr
  430. AddReplyBool ( AppleEvent * event , AppleEvent * reply , Boolean val ) {
  431.  
  432. OSErr err = 0 ;
  433. DescType theType , aType ;
  434. long theSize ;
  435. AEDesc list = { 0 , 0 } ;
  436.  
  437.     if ( AEGetKeyDesc ( event , keyAERequestedType , typeAEList , & list ) ) {
  438.         theType = typeBest ;
  439.     }
  440.     if ( ! err ) {
  441.         err = errAECantSupplyType ;
  442.         if ( list . dataHandle ) {
  443.  
  444.         long numItems ;
  445.         long theItem ;
  446.         AEKeyword foom ;
  447.  
  448.             err = AECountItems ( & list , & numItems ) ;
  449.             for ( theItem = 1 ; theItem <= numItems && ! err ; theItem ++ ) {
  450.                 err = AEGetNthPtr ( & list , theItem , typeType , & foom ,
  451.                     & aType , ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  452.                 switch ( theType ) {
  453.                 case typeChar :
  454.                     theItem = numItems ;
  455.                     break ;
  456.                 case typeBoolean :
  457.                     theItem = numItems ; /* break out */
  458.                     break ;
  459.                 case typeBest :
  460.                     theType = typeBoolean ;
  461.                     theItem = numItems ; /* break out */
  462.                     break ;
  463.                 }
  464.             }
  465.         }
  466.     }
  467.     if ( ! err ) {
  468.     static Str63 s ;
  469.         switch ( theType ) {
  470.         case typeBoolean :
  471.             err = AEPutParamPtr ( reply , keyAEResult , typeBoolean , ( void * ) & val ,
  472.                 sizeof ( val ) ) ;
  473.             break ;
  474.         case typeChar :
  475.             GetIndString ( s , 127 , val ? 2 : 1 ) ;
  476.             err = AEPutParamPtr ( reply , keyAEResult , typeChar , ( void * ) & s [ 1 ] ,
  477.                 s [ 0 ] ) ;
  478.             break ;
  479.         default :
  480.             err = errAECantSupplyType ;
  481.             break ;
  482.         }
  483.     }
  484.     AEDisposeDesc ( & list ) ;
  485.     return err ;
  486. }
  487.  
  488.  
  489. static OSErr
  490. AddReplyLong ( AppleEvent * event , AppleEvent * reply , long val ) {
  491.  
  492. OSErr err = 0 ;
  493. DescType theType , aType ;
  494. long theSize ;
  495. AEDesc list = { 0 , 0 } ;
  496.  
  497.     if ( AEGetKeyDesc ( event , keyAERequestedType , typeAEList , & list ) ) {
  498.         theType = typeBest ;
  499.     }
  500.     if ( ! err ) {
  501.         err = errAECantSupplyType ;
  502.         if ( list . dataHandle ) {
  503.  
  504.         long numItems ;
  505.         long theItem ;
  506.         AEKeyword foom ;
  507.  
  508.             err = AECountItems ( & list , & numItems ) ;
  509.             for ( theItem = 1 ; theItem <= numItems && ! err ; theItem ++ ) {
  510.                 err = AEGetNthPtr ( & list , theItem , typeType , & foom ,
  511.                     & aType , ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  512.                 switch ( theType ) {
  513.                 case typeChar :
  514.                 case typeMagnitude :
  515.                 case typeLongInteger :
  516.                 case typeBest :
  517.                     theType = typeInteger ;
  518.                     theItem = numItems ; /* break out */
  519.                     break ;
  520.                 }
  521.             }
  522.         }
  523.     }
  524.     if ( ! err ) {
  525.         switch ( theType ) {
  526.         case typeInteger :
  527.             err = AEPutParamPtr ( reply , keyAEResult , typeInteger , ( void * ) & val ,
  528.                 sizeof ( val ) ) ;
  529.             break ;
  530.         default :
  531.             err = errAECantSupplyType ;
  532.             break ;
  533.         }
  534.     }
  535.     AEDisposeDesc ( & list ) ;
  536.     return err ;
  537. }
  538.  
  539.  
  540. static pascal OSErr
  541. GetData ( AppleEvent * event , AppleEvent * reply , long refCon ) {
  542.  
  543. AERecord theSpec = { 0 , 0 } ;
  544. DescType theType , aType ;
  545. long theSize ;
  546. OSErr err ;
  547.  
  548.     TRY {
  549.         err = AEGetKeyDesc ( event , keyDirectObject , typeAERecord , & theSpec ) ;
  550.         if ( ! err ) {
  551.             err = AEGetKeyPtr ( & theSpec , keyAEDesiredClass , typeType , & aType ,
  552.                 ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  553.         }
  554.         if ( ! err ) {
  555.             if ( cProperty != theType ) {
  556.                 err = errAENotAnElement ;
  557.             } else {
  558.                 err = AEGetKeyPtr ( & theSpec , keyAEKeyData , typeType , & aType ,
  559.                     ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  560.             }
  561.         }
  562.         if ( ! err ) {
  563.             switch ( theType ) {
  564.             case pTurnover :
  565.                 err = AddReplyLong ( event , reply , gPrefStruct . turnoverPeriod ) ;
  566.                 break ;
  567.             case pOptionKeyTalk :
  568.                 err = AddReplyBool ( event , reply , gPrefStruct . talkOptionKey ) ;
  569.                 break ;
  570.             case pControlKeyTalk :
  571.                 err = AddReplyBool ( event , reply , gPrefStruct . talkControlKey ) ;
  572.                 break ;
  573.             case pCommandKeyTalk :
  574.                 err = AddReplyBool ( event , reply , gPrefStruct . talkCommandKey ) ;
  575.                 break ;
  576.             case pShiftKeyTalk :
  577.                 err = AddReplyBool ( event , reply , gPrefStruct . talkShiftKey ) ;
  578.                 break ;
  579.             case pCapsLockKeyTalk :
  580.                 err = AddReplyBool ( event , reply , gPrefStruct . talkCapsLockKey ) ;
  581.                 break ;
  582.             case pFiveMinuteTalk :
  583.                 err = AddReplyBool ( event , reply , gPrefStruct . talkConstantly ) ;
  584.                 break ;
  585.             default :
  586.                 err = errAENotAnElement ;
  587.             }
  588.         }
  589.         AEDisposeDesc ( & theSpec ) ;
  590.     } CATCH {
  591.         AEDisposeDesc ( & theSpec ) ;
  592.         err = __err ;
  593.         NO_PROPAGATE ;
  594.     } DONE ;
  595.     return err ;
  596. }
  597.  
  598.  
  599. static OSErr
  600. GetVal ( AppleEvent * event , DescType type , void * data , long size ) {
  601.  
  602. DescType theType ;
  603. long theSize ;
  604. OSErr err ;
  605.  
  606.     err = AEGetParamPtr ( event , keyAEData , type , & theType , ( void * ) data ,
  607.         size , & theSize ) ;
  608.     if ( ! err ) {
  609.         if ( type != theType ) {
  610.             DebugStr ( "\pReal type error" ) ;
  611.             err = errAETypeError ;
  612.         }
  613.     }
  614.     return err ;
  615. }
  616.  
  617.  
  618. static pascal OSErr
  619. SetData ( AppleEvent * event , AppleEvent * reply , long refCon ) {
  620.  
  621. AERecord theSpec = { 0 , 0 } ;
  622. DescType theType , aType ;
  623. long theSize ;
  624. OSErr err ;
  625.  
  626.     TRY {
  627.         err = AEGetKeyDesc ( event , keyDirectObject , typeAERecord , & theSpec ) ;
  628.         if ( ! err ) {
  629.             err = AEGetKeyPtr ( & theSpec , keyAEDesiredClass , typeType , & aType ,
  630.                 ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  631.         }
  632.         if ( ! err ) {
  633.             if ( cProperty != theType ) {
  634.                 err = errAENotAnElement ;
  635.             } else {
  636.                 err = AEGetKeyPtr ( & theSpec , keyAEKeyData , typeType , & aType ,
  637.                     ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  638.             }
  639.         }
  640.         if ( ! err ) {
  641.         Pref savePref = gPrefStruct ;
  642.         long l ;
  643.         Boolean b ;
  644.             switch ( theType ) {
  645.             case pTurnover :
  646.                 err = GetVal ( event , typeInteger , & l , sizeof ( l ) ) ;
  647.                 if ( ! err ) gPrefStruct . turnoverPeriod = l ;
  648.                 break ;
  649.             case pOptionKeyTalk :
  650.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  651.                 if ( ! err ) gPrefStruct . talkOptionKey = b ;
  652.                 break ;
  653.             case pControlKeyTalk :
  654.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  655.                 if ( ! err ) gPrefStruct . talkControlKey = b ;
  656.                 break ;
  657.             case pCommandKeyTalk :
  658.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  659.                 if ( ! err ) gPrefStruct . talkCommandKey = b ;
  660.                 break ;
  661.             case pShiftKeyTalk :
  662.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  663.                 if ( ! err ) gPrefStruct . talkShiftKey = b ;
  664.                 break ;
  665.             case pCapsLockKeyTalk :
  666.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  667.                 if ( ! err ) gPrefStruct . talkCapsLockKey = b ;
  668.                 break ;
  669.             case pFiveMinuteTalk :
  670.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  671.                 if ( ! err ) gPrefStruct . talkConstantly = b ;
  672.                 break ;
  673.             default :
  674.                 err = errAENotAnElement ;
  675.             }
  676.             if ( err ) {
  677.                 gPrefStruct = savePref ;
  678.             }
  679.         }
  680.         AEDisposeDesc ( & theSpec ) ;
  681.     } CATCH {
  682.         AEDisposeDesc ( & theSpec ) ;
  683.         err = __err ;
  684.         NO_PROPAGATE ;
  685.     } DONE ;
  686.     return err ;
  687. }
  688.  
  689.  
  690. static pascal OSErr
  691. AESpeakTime ( AppleEvent * event , AppleEvent * reply , long refCon ) {
  692.  
  693. TalkTime tt ;
  694. short err = 0 ;
  695.  
  696.     TRY {
  697.         MakeTalkTime ( & tt ) ;
  698.         Talk ( & tt ) ;
  699.     } CATCH {
  700.         err = __err ;
  701.         NO_PROPAGATE ;
  702.     } DONE ;
  703.  
  704.     return err ;
  705. }
  706.  
  707.  
  708. static pascal OSErr
  709. AESpeakDate ( AppleEvent * event , AppleEvent * reply , long refCon ) {
  710.  
  711. short err = 0 ;
  712.  
  713.     TRY {
  714.         SpeakDate ( ) ;
  715.     } CATCH {
  716.         err = __err ;
  717.         NO_PROPAGATE ;
  718.     } DONE ;
  719.  
  720.     return err ;
  721. }
  722.  
  723.  
  724. static pascal OSErr
  725. AETextToBool ( DescType typeCode , Ptr dataPtr , Size dataSize ,
  726.     DescType toType , long refCon , AEDesc * result ) {
  727.  
  728. static Str63 s ;
  729. static Str63 com ;
  730. Boolean b = 0 ;
  731.  
  732.     if ( dataSize > 63 ) {
  733.         return errAECantSupplyType ;
  734.     }
  735.     if ( typeCode == typeChar && toType == typeBoolean ) {
  736.         com [ 0 ] = dataSize ;
  737.         BlockMove ( dataPtr , & com [ 1 ] , com [ 0 ] ) ;
  738.         GetIndString ( s , 127 , 1 ) ;
  739.         if ( ! IUEqualString ( s , com ) ) {
  740.             b = 0 ;
  741.             return AECreateDesc ( typeBoolean , ( Ptr ) & b , sizeof ( b ) , result ) ;
  742.         }
  743.  
  744.         GetIndString ( s , 127 , 2 ) ;
  745.         if ( ! IUEqualString ( s , com ) ) {
  746.             b = 1 ;
  747.             return AECreateDesc ( typeBoolean , ( Ptr ) & b , sizeof ( b ) , result ) ;
  748.         }
  749.     }
  750.     return errAECantSupplyType ;
  751. }
  752.  
  753.  
  754. static void
  755. InstallHandlers ( void ) {
  756.  
  757.     FailErr ( AEInstallEventHandler ( kCoreEventClass , kAEOpenApplication ,
  758.         ( void * ) OpenApplication , 0L , 0 ) ) ;
  759.     FailErr ( AEInstallEventHandler ( kCoreEventClass , kAEQuitApplication ,
  760.         ( void * ) QuitApplication , 0L , 0 ) ) ;
  761.     FailErr ( AEInstallEventHandler ( kAECoreSuite , kAEGetData ,
  762.         ( void * ) GetData , 0L , 0 ) ) ;
  763.     FailErr ( AEInstallEventHandler ( kAECoreSuite , kAESetData ,
  764.         ( void * ) SetData , 0L , 0 ) ) ;
  765.     FailErr ( AEInstallEventHandler ( kAETalkingClockSuite , kAESayTime ,
  766.         ( void * ) AESpeakTime , 0L , 0 ) ) ;
  767.     FailErr ( AEInstallEventHandler ( kAETalkingClockSuite , kAESayDate ,
  768.         ( void * ) AESpeakDate , 0L , 0 ) ) ;
  769.  
  770.     FailErr ( AEInstallCoercionHandler ( typeChar , typeBoolean , AETextToBool ,
  771.         0L , 0 , 0 ) ) ;
  772. }
  773.